﻿namespace Leo.Core.Common
{
    public static class TreeEnumerableExtensions
    {

        /// <summary>
        ///     实现接口 ITreeItem 对象列表转成树对象列表
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <typeparam name="TK">id 字段类型</typeparam>
        /// <param name="collection">列表对象</param>
        /// <param name="idSelector">唯一字段</param>
        /// <param name="parentIdSelector">上级字段</param>
        /// <param name="rootId">根节点值</param>
        /// <returns></returns>
        public static IEnumerable<T> ToTree<T, TK>(
            this IEnumerable<T> collection,
            Func<T, TK> idSelector,
            Func<T, TK> parentIdSelector,
            TK? rootId = default) where T : class, ITreeItem<T>, new()
        {
            IEnumerable<T> treeItems = collection as T[] ?? collection.ToArray();
            foreach (T? c in treeItems.Where(c => EqualityComparer<TK>.Default.Equals(parentIdSelector(c), rootId)))
            {
                c.Children = treeItems.ToTree(idSelector, parentIdSelector, idSelector(c)).ToList();
                yield return c;
            }
        }

        /// <summary>
        ///     基于 TreeResult 类的对象列表转成树对象列表
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="collection">列表对象</param>
        /// <returns></returns>
        public static IEnumerable<T> ToTree<T>(this List<T> collection) where T : TreeResult<T>, new()
        {
            Guid IdSelector(T x)
            {
                return x.Id;
            }

            Guid ParentIdSelector(T x)
            {
                return x.ParentId ?? Guid.Empty;
            }

            Guid rootId = Guid.Empty;
            return collection.ToTree(IdSelector, ParentIdSelector, rootId);
        }

        /// <summary>
        ///     任意对象列表转树对象列表
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <typeparam name="TK">id 字段类型</typeparam>
        /// <param name="collection">列表对象</param>
        /// <param name="idSelector">唯一字段</param>
        /// <param name="parentIdSelector">上级字段</param>
        /// <param name="rootId">根节点值</param>
        /// <returns></returns>
        public static IEnumerable<TreeItem<T>> GenTree<T, TK>(
            this IEnumerable<T> collection,
            Func<T, TK> idSelector,
            Func<T, TK> parentIdSelector,
            TK? rootId = default)
        {
            IEnumerable<T> enumerable = collection as T[] ?? collection.ToArray();
            foreach (T c in enumerable.Where(c => EqualityComparer<TK>.Default.Equals(parentIdSelector(c), rootId)))
            {
                yield return new TreeItem<T>
                {
                    Item = c,
                    Children = enumerable.GenTree(idSelector, parentIdSelector, idSelector(c))
                };
            }
        }
    }
}
